package com.share.common.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;

/**
 * 加载非压缩的文件
 */
@Slf4j
public class JarFileUtil {
    final static String META_INF = "META-INF";
    final static String BOOT_INF = "BOOT-INF";
    final static String BOOT_INF_CLASSES = "BOOT-INF.classes";
    final static String BOOT_INF_LIB = "BOOT-INF.lib";

    public static void main(String[] args) {
        String str = getMainPackage("D:\\project\\we-share\\share-admin\\target\\share-admin\\BOOT-INF\\lib\\aspectjweaver-1.9.5.jar");
        System.out.println(str);
    }

    //获取主要的包
    public static String getMainPackage(String jarFileName) {
        String rePak = null;
        List<String> list = listPackage(jarFileName);
        int size = list.size();
        TreeMap<Double, String> map = new TreeMap(Collections.reverseOrder());
        for (String pak : list) {
            if (pak.split("\\.").length <= 1) {
                rePak = pak;
                continue;
            }
            long count = list.stream().filter(e -> e.contains(pak)).count();
            if (count <= 1) {
                continue;
            }
            map.put(count * 1.0 / size, pak);
        }

        if (map.size() > 0) {
            List<Double> list1 = map.keySet().stream().filter(e -> e > 0.9).collect(Collectors.toList());
            Double key = null;
            if (list1.size() > 0) {
                key = list1.get(list1.size() - 1);
            } else {
                key = map.firstEntry().getKey();
            }
            rePak = map.get(key);
        }
        return rePak;
    }

    /**
     * org.springframework.boot.loader.jar
     * abc.jar
     *
     * @param jarFileName
     * @return 返回jar文件中所有的文件列表
     */
    public static List<String> listPackage(String jarFileName) {
        List<String> fileNameList = new LinkedList<>();
        try {
            JarFile jarFile = new JarFile(jarFileName);
            Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
            while (jarEntryEnumeration.hasMoreElements()) {
                JarEntry jarEntry = jarEntryEnumeration.nextElement();
                if (jarEntry.isDirectory()) {
                    String name = jarEntry.getName();
                    name = name.substring(0, name.length() - 1).replaceAll("/", ".");
                    if (name.startsWith(META_INF)) {
                        continue;
                    }

                    if (name.equals(BOOT_INF) || name.equals(BOOT_INF_CLASSES) || name.equals(BOOT_INF_LIB)) {
                        continue;
                    }

                    if (name.startsWith(BOOT_INF_CLASSES)) {
                        name = name.substring(BOOT_INF_CLASSES.length() + 1);
                    }

                    if (StringUtils.isBlank(name)) {
                        continue;
                    }
                    fileNameList.add(name);
                }
            }
        } catch (IOException e) {
            log.error("jar文件读取异常", e);
        }

        return fileNameList;
    }

    /**
     * org/springframework/boot/loader/jar/JarFile$2.class
     * abc.jar
     *
     * @param jarFileName
     * @return 返回jar文件中所有的文件列表
     */
    public static List<String> listFileName(String jarFileName) {
        List<String> fileNameList = new LinkedList<>();
        try {
            JarFile jarFile = new JarFile(jarFileName);
            Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
            while (jarEntryEnumeration.hasMoreElements()) {
                JarEntry jarEntry = jarEntryEnumeration.nextElement();

                if (!jarEntry.isDirectory()) {
                    String name = jarEntry.getName();
                    fileNameList.add(name);
                }
            }
        } catch (IOException e) {
            log.error("jar文件读取异常", e);
        }

        return fileNameList;
    }

    public static Map<String, byte[]> mapJarContent(String jarFilePath) {
        File file = new File(jarFilePath);
        return mapJarContent(file);
    }

    /**
     * 读取jar文件的内容，跳过jar包里面的jar文件
     *
     * @param jarFileName
     * @return key是文件名, value是文件内容
     */
    public static Map<String, byte[]> mapJarContent(File jarFileName) {
        Map<String, byte[]> contentMap = new HashMap<>();
        try {
            JarFile jarFile = new JarFile(jarFileName);
            Enumeration<JarEntry> jarEntryEnumeration = jarFile.entries();
            while (jarEntryEnumeration.hasMoreElements()) {
                JarEntry fileEntry = jarEntryEnumeration.nextElement();
                String name = fileEntry.getName();
                if (!fileEntry.isDirectory() && !name.endsWith(".jar")) {

                    ZipEntry entry = jarFile.getEntry(name);//name 最开头没有/,换句话就是相对路径
                    try {
                        InputStream inputStream = jarFile.getInputStream(entry);
                        byte[] bytes = IoUtil.readByte(inputStream);
                        contentMap.put(name, bytes);
                    } catch (Exception e) {
                        log.error("jar文件内容读取异常", e);
                    }
                }
            }
        } catch (IOException e) {
            log.error("jar文件读取异常", e);
        }
        return contentMap;
    }
}
